Go语言中没有枚举这个关键字,这会让人很不解,突然想用到的时候,会觉得很不适应。我不用不代表不要有,这可能是Go语言开发的取舍问题,追求精简,去掉不值得的地方。

缘起

在开源项目BaiduPCS-Go中,有这样的一个操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const (
// B byte
B = (int64)(1 << (10 * iota))
// KB kilobyte
KB
// MB megabyte
MB
// GB gigabyte
GB
// TB terabyte
TB
// PB petabyte
PB
)

从代码里头都可以猜到,iota这肯定是递增的,看定义,其初始值为0

1
const iota int = 0

具体对于iota的理解,可以参考:4 iota enum examples

Iota基本的例子

  • iota关键字代表连续整数的常数0,1,2,…
  • 只要const出现在源代码中,它就会重置为0 ,
  • 并在每个const之后递增。
1
2
3
4
5
6
const (
C0 = iota
C1 = iota
C2 = iota
)
fmt.Println(C0, C1, C2) // "0 1 2"

这可以简化为

1
2
3
4
5
const (
C0 = iota
C1
C2
)

在这里,我们依赖于在带括号的const声明中隐式重复表达式的事实——表示前面的表达式及其类型的重复。

从一开始

要以1而不是0开始常量列表,可以iota在算术表达式中使用。

1
2
3
4
5
6
const (
C1 = iota + 1
C2
C3
)
fmt.Println(C1, C2, C3) // "1 2 3"

跳过定义

您可以使用空白标识符跳过常量列表中的值。

1
2
3
4
5
6
7
const (
C1 = iota + 1
_
C3
C4
)
fmt.Println(C1, C3, C4) // "1 3 4"

带字符串的完整枚举类型[最佳实践]

这是实现枚举类型的惯用方法:

  • 创建一个新的整数类型,
  • 列出其值,使用iota
  • 给类型一个String函数。
1
2
3
4
5
6
7
8
9
10
11
12
type Direction int

const (
North Direction = iota
East
South
West
)

func (d Direction) String() string {
return [...]string{"North", "East", "South", "West"}[d]
}

Ex…

1
2
3
4
5
6
7
8
9
10
11
var d Direction = North
fmt.Print(d)
switch d {
case North:
fmt.Println(" goes up.")
case South:
fmt.Println(" goes down.")
default:
fmt.Println(" stays put.")
}
// Output: North goes up.